/***************************************
	文件：GoapFactory.cs
	作者：林文豪
	日期：2021-05-05
	功能：1、
****************************************/

using System.Collections.Generic;
using MyGame.Character;
using MyGame.Global;
using UnityEngine;
using UnityEngine.PlayerLoop;

namespace MyGame.AI.GOAP {
	public class GoapFactory {
		private int                                            _CreateCount;
		private Dictionary<EnemyType, PlannerWithMultiwayTree> _GoalMap;

		private GoapFactory() {
			_GoalMap = new Dictionary<EnemyType, PlannerWithMultiwayTree>();
		}

		public static readonly GoapFactory Instance = new GoapFactory();

		public Enemy GenerateEnemy(EnemyType enemyType) {
			Enemy               enemy     = new GameObject(enemyType +"_"+ _CreateCount, typeof(Enemy)).GetComponent<Enemy>();
			EnemyGoapStaticData excelData = EnemyGoapStaticData.FindEntity(data => enemyType == data.EnemyType);
			enemy.Init(excelData);
			_CreateCount++;
			return enemy;
		}

		public PlannerWithMultiwayTree GeneratePlanner(Enemy enemy) {
			List<IGoal>   allGoals   = new List<IGoal>();
			List<IAction> allActions = new List<IAction>();

			EnemyGoapStaticData enemyExcelData = EnemyGoapStaticData.FindEntity(data => data.EnemyType == enemy.ExcelData.EnemyType);
			foreach (GoapGoalType goal in enemyExcelData.AllGoals) {
				allGoals.Add(GenerateGoal(goal, enemy));
			}
			foreach (GoapActionType action in enemyExcelData.AllActions) {
				allActions.Add(GenerateAction(action, enemy));
			}

			return new PlannerWithMultiwayTree(allGoals, allActions);
		}

		public IGoal GenerateGoal(GoapGoalType goalType, Enemy owner) {
			GoapGoalData excelData = GoapGoalData.FindEntity(data => data.GoalType == goalType);
			switch (goalType) {
				case GoapGoalType.Chase:
					return new GoapGoalChase(excelData, owner);
				case GoapGoalType.Patrol:
					return new GoapGoalPatrol(excelData, owner);
			}
			return null;
		}
		public IAction GenerateAction(GoapActionType actionType, Enemy owner) {
			GoapActionData excelData = GoapActionData.FindEntity(data => data.ActionType == actionType);
			switch (actionType) {
				case GoapActionType.Goto:
					return new GoapActionGoTo(excelData, owner);
				case GoapActionType.FindOpponent:
					return new GoapActionFindOpponent(excelData, owner);
			}

			return null;
		}

		private GoapConditionContainer GenerateConditionContainer(GoapConditionType conditionType) {
			switch (conditionType) {
				default:
					return new GoapConditionContainer(conditionType.ToString(), true);
			}
		}

		public GoapCondition GenerateCondition(List<GoapConditionType> conditionTypes) {
			List<GoapConditionContainer> containers = new List<GoapConditionContainer>();
			foreach (GoapConditionType conditionType in conditionTypes) {
				containers.Add(GenerateConditionContainer(conditionType));
			}

			return new GoapCondition(containers);
		}

		public MultiwayTree GenerateMultiwayTree(IGoal goal, List<IAction> actions) {
			MultiwayTree tree = new MultiwayTree(goal, actions);
			return tree;
		}
	}
}
